/**************************************************************************
** Qt Creator license header template
**   Special keywords: Programmer 2012/3/21 2012
**   Environment variables: 
**   To protect a percent sign, use '%'.
**************************************************************************/
#include <vcg/complex/algorithms/clean.h>

#include "meshsimplificationquadric.h"


//void MeshSimplificationQuadric::getParams(vcg::tri::TriEdgeCollapseQuadricParameter& params)
//{}

void QuadricSimplification(MyTriMesh& m, int targetFaceNum, bool selected, vcg::tri::TriEdgeCollapseQuadricParameter& pp, GLArea* gl)
{
    vcg::math::Quadric<double> QuadricZero;
    QuadricZero.SetZero();
    QuadricTemp TempData(m.vert,QuadricZero);
    Helper::TDp() = &TempData;

    if(selected) // simplify only inside selected faces
      {
        // select only the vertices having ALL incident faces selected
        vcg::tri::UpdateSelection<MyTriMesh>::VertexFromFaceStrict(m);

        // Mark not writable un-selected vertices
        MyTriMesh::VertexIterator  vi;
        for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
        {
              if(!(*vi).IsS()) (*vi).ClearW();
                          else (*vi).SetW();
        }
      }

      if(pp.PreserveBoundary && !selected)
        {
        pp.FastPreserveBoundary=true;
            pp.PreserveBoundary = false;
        }

      if(pp.NormalCheck) pp.NormalThrRad = M_PI/4.0;


      vcg::LocalOptimization<MyTriMesh> DeciSession(m,&pp);
        //cb(1,"Initializing simplification");
        DeciSession.Init<MeshSimplificationQuadric>();

        //if(selected)
            //targetFaceNum= m.fn - (m.sfn-targetFaceNum);
        DeciSession.SetTargetSimplices(targetFaceNum);
        DeciSession.SetTimeBudget(0.1f); // this allow to update the progress bar 10 time for sec...
    //  if(TargetError< numeric_limits<double>::max() ) DeciSession.SetTargetMetric(TargetError);
      //int startFn=m.fn;
      int faceToDel = m.fn-targetFaceNum;
     while( DeciSession.DoOptimization() && m.fn > targetFaceNum )
     {
        gl->updateGL();
       //cb(100-100*(m.fn-TargetFaceNum)/(faceToDel), "Simplifying...");
     }

        DeciSession.Finalize<MeshSimplificationQuadric>();

//      if(selected) // Clear Writable flags
//      {
//        MyTriMesh::VertexIterator  vi;
//        for(vi=m.vert.begin();vi!=m.vert.end();++vi)
//          if(!(*vi).IsD()) (*vi).SetW();
//      }


//      if(true)//par.getBool("AutoClean"))
//              {
//                  int nullFaces=vcg::tri::Clean<MyTriMesh>::RemoveFaceOutOfRangeArea(m,0);
//                  //if(nullFaces) Log( "PostSimplification Cleaning: Removed %d null faces", nullFaces);
//                  int deldupvert=vcg::tri::Clean<MyTriMesh>::RemoveDuplicateVertex(m);
//                  //if(deldupvert) Log( "PostSimplification Cleaning: Removed %d duplicated vertices", deldupvert);
//                  int delvert=vcg::tri::Clean<MyTriMesh>::RemoveUnreferencedVertex(m);
//                  //if(delvert) Log( "PostSimplification Cleaning: Removed %d unreferenced vertices",delvert);
//                  //m.clearDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
//                  //vcgtri::Allocator<CMeshO>::CompactVertexVector(m.cm);
//                  //tri::Allocator<CMeshO>::CompactFaceVector(m.cm);
//              }

              vcg::tri::UpdateNormals<MyTriMesh>::PerVertexNormalizedPerFace(m);
              vcg::tri::UpdateBounding<MyTriMesh>::Box(m);
}
